<?php

class isParser {
    var $cData;
    var $depth;
    var $tagStack;
    var $currentLine = 0;
    var $currentFile = "";
    var $lineStack = array();
    var $line;

    //doc parsen
    function parse ($fcontents) {
        if (is_array($fcontents)) {
        // jede zeile
            foreach ($fcontents As $line) {
                $this->line = $line;
                if (preg_match('/^@@@(begin|end)/', $line, $matches)) {
                    if ($matches[1] == 'begin') {
                        $this->lineStack[] = array(
                            'lines' => $this->currentLine,
                            'file'  => $this->currentFile
                        );
                        $this->currentLine = 0;
                        $parts = split(' ', $line);
                        $this->currentFile = $parts[1];
                        continue;
                    } elseif ($matches[1] == 'end') {
                        $lineElem = array_pop($this->lineStack);
                        $this->currentLine = $lineElem['lines'];
                        $this->currentFile = $lineElem['file'];
                        continue;
                    }
                } else {
                    $this->currentLine++;
                }
                $this->parseLine($line);
            }
        }
        $this->cData('isml',$this->cData);
        if (count($this->tagStack) > 0) {
            die("<strong>Parserfehler:</strong> ".strtolower(array_pop($this->tagStack))." erwartet am Ende des Template!");
        }
    }

    // is:tag aufsplitten
    function splitTag ($tagStr) {
        preg_match('/<(\/{0,1})(is:[\w_-]+)(.*?)(\/{0,1})>/i',$tagStr,$matches);
        if ($matches[1]=='/') $tag['type'] = 1;
        $tag['name'] = strtoupper($matches[2]);
        if (trim($matches[3])) {
            $pairs = preg_split('/" +/',preg_replace('/"$/','',trim($matches[3])));
            for ($i=0;$i<count($pairs);$i++) {
                @list($name,$val) = split('="',$pairs[$i]);
                $tag['attrs'][strtoupper($name)] = preg_replace('/^"/','',$val);
            }
        }
        if ($matches[4]=='/') $tag['type'] = 2;
        return $tag;
    }

    function parseLine ($line) {
        while (preg_match('/^(.*?)(<\/{0,1}is:.*?>)(.*)$/ims',$line,$matches)) {
            $tag = $this->splitTag($matches[2]);
            $this->cData .= $matches[1];
            if (empty($tag['type'])) {
                $this->depth++;
                $this->cData('isml',$this->cData);
                $this->cData = '';
                $this->startElementWrap('isml',$tag['name'],$tag['attrs']);
            } elseif ($tag['type']==1) {
                $this->depth--;
                $this->cData('isml',$this->cData);
                $this->cData = '';
                $this->endElementWrap('isml',$tag['name']);
            } elseif ($tag['type']==2) {
                $this->cData('isml',$this->cData);
                $this->cData = '';
                $this->finitElement('isml',$tag['name'],$tag['attrs']);
            }
            $line = $matches[3];
        }
        $this->cData .= $line;
    }

    function startElementWrap($parser, $name, $attrs) {
        $this->tagStack[] = $name;
        $this->startElement($parser, $name, $attrs);
    }

    function endElementWrap($parser, $name) {
        $tagname = array_pop($this->tagStack);
        if ($tagname != $name) die('<strong>Parserfehler:</strong> '.strtolower($tagname).' erwartet aber '.strtolower($name).' gefunden in Zeile '.$this->currentLine.' in Datei '.$this->currentFile);
        $this->endElement($parser, $name);
    }

    // abstract
    function startElement($parser, $name, $attrs) {
    }

    // abstract
    function finitElement($parser, $name, $attrs) {
    }

    // abstract
    function endElement($parser, $name) {
    }

    // abstract
    function cData($parser, $data) {
    }

}

?>
